const PADDING = 'padding';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {

  constructor(executor) {//原生class必须在构造函数中声明属性；且必须有值

    this.status = PADDING
    this.successCallbacks = []
    this.failCallbacks = []
    this.value = undefined
    this.reason = undefined

    this.resolve = (value) => {//箭头函数：外部调用该方法不改变this,始终指向当前实例对象
      if (this.status !== PADDING) return
      this.status = FULFILLED
      this.value = value
      while (this.successCallbacks.length) {//回调队列，先入先出
        this.successCallbacks.shift()(this.value)
      }
    }

    this.reject = (reason) => {//箭头函数：外部调用该方法不改变this,始终指向当前实例对象
      if (this.status !== PADDING) return
      this.status = REJECTED
      this.reason = reason
      while (this.failCallbacks.length) {//回调队列，先入先出
        this.failCallbacks.shift()(this.reason)
      }
    }
    try {
      executor(this.resolve, this.reject)
    } catch (error) {
      this.reject(error)
    }
  }


  then (resolveCallback, rejectCallback) {
    /**
      * 一、同步与异步逻辑
      * 1. 同步代码会直接执行
      * 2. 异步代码会将成功回调、失败回调存储起来。触发承诺结果时再调用
      */
    /**
     * 二、回调函数返回值两种情况：普通值 vs promise对象
     * 1. 普通值，直接调用实例方法resolve传递。
     * 2. promise对象，看该对象的两种状态，把结果通过resolve或者reject传递。
     */
    const newPromise = new Promise((resolve, reject) => {
      if (this.status === FULFILLED) {
        //! 用异步代码获取newPromise,x
        setTimeout(() => {
          try {
            const x = resolveCallback(this.value)
            resolvePromise(newPromise, x, resolve, reject)
          } catch (error) {
            reject(error)
          }
        }, 0)
      } else if (this.status === REJECTED) {

        setTimeout(() => {
          try {
            const x = rejectCallback(this.reason)
            resolvePromise(newPromise, x, resolve, reject)
          } catch (error) {
            reject(error)
          }
        }, 0)
      } else if (this.status === PADDING) {//异步存储
        this.successCallbacks.push(resolveCallback)
        this.failCallbacks.push(rejectCallback)
      }
    })
    return newPromise
  }

}

// 解析promise对象
function resolvePromise (newPromise, x, resolve, reject) {
  if (x === newPromise) {//反回了他本身，循环调用报错
    return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
  }
  if (x instanceof MyPromise) {//promise对象

    x.then(resolve, reject)
  } else {
    resolve(x)
  }
}

export default MyPromise